package net.maku.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import lombok.AllArgsConstructor;
import net.maku.events.vo.ActivityJoinOrgBaseVO;
import net.maku.framework.common.constant.Constant;
import net.maku.framework.common.exception.ServerException;
import net.maku.framework.common.utils.PageResult;
import net.maku.framework.common.utils.TreeUtils;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.framework.security.user.SecurityUser;
import net.maku.propagate.vo.VisibleOrgBaseVO;
import net.maku.system.convert.SysOrgConvert;
import net.maku.system.convert.SysUserConvert;
import net.maku.system.dao.SysOrgDao;
import net.maku.system.dao.SysOrgMemberDao;
import net.maku.system.dao.SysUserDao;
import net.maku.system.entity.SysOrgEntity;
import net.maku.system.entity.SysOrgMemberEntity;
import net.maku.system.entity.SysOrgTransferEntity;
import net.maku.system.entity.SysUserEntity;
import net.maku.system.enums.SuperAdminEnum;
import net.maku.system.query.SysOrgQuery;
import net.maku.system.service.SysOrgService;
import net.maku.system.service.SysOrgTransferService;
import net.maku.system.vo.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 机构管理
 *
 * @author 阿沐 babamu@126.com
 * <a href="https://maku.net">MAKU</a>
 */
@Service
@AllArgsConstructor
public class SysOrgServiceImpl extends BaseServiceImpl<SysOrgDao, SysOrgEntity> implements SysOrgService {
    private final SysUserDao sysUserDao;
    private final SysOrgTransferService sysOrgTransferService;
    private final SysOrgMemberDao sysOrgMemberDao;
    private final PasswordEncoder passwordEncoder;

    @Override
    public PageResult<SysOrgVO> page(SysOrgQuery query) {
        return getPageResult(query);
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        SysOrgEntity org = this.getById(id);
        SysOrgEntity entity = new SysOrgEntity();
        entity.setId(id);
        entity.setPid(org.getPid());
        entity.setStatus(status);
        baseMapper.updateById(entity);
    }

    private PageResult<SysOrgVO> getPageResult(SysOrgQuery query) {
        IPage<SysOrgEntity> page = getPage(query);
        Map<String, Object> params = shareQuery(query);
        params.put(Constant.PAGE, page);
        List<SysOrgEntity> entityList = baseMapper.getList(params);
        return new PageResult<>(BeanUtil.copyToList(entityList, SysOrgVO.class), page.getTotal());
    }

    private Map<String, Object> shareQuery(SysOrgQuery query) {
        Map<String, Object> params = new HashMap<>();
        params.put("name", query.getName());
        params.put("whetherPurchase", query.getWhetherPurchase());
        params.put("unionType", query.getUnionType());
        if (CollectionUtils.isNotEmpty(query.getOrgIdList())) {
            params.put("orgIdList", query.getOrgIdList());
        }
        if (ObjectUtils.isNotEmpty(query.getAuditStatus())) {
            params.put("auditStatus", query.getAuditStatus());
        }
        if (ObjectUtils.isNotEmpty(query.getStatus())) {
            params.put("status", query.getStatus());
        }
        if (ObjectUtils.isNotEmpty(query.getPId())) {
            params.put("orgIdList", getSubOrgIdList(query.getPId()));
        } else {
            // 数据权限
            params.put(Constant.DATA_SCOPE, getDataScope("t1", "id"));
        }
        return params;
    }

    @Override
    public PageResult<SysOrgVO> applyPage(SysOrgQuery query) {
        query.setAuditStatus(0);
        return getPageResult(query);
    }

    @Override
    public PageResult<TransferOrgVO> transferPage(SysOrgQuery query) {
        List<TransferOrgVO> result = new ArrayList<>();
        IPage<SysOrgTransferEntity> page = sysOrgTransferService.getSysOrgTransfer(new Page<>(query.getPage(), query.getLimit()));
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            query.setOrgIdList(page.getRecords().stream().map(SysOrgTransferEntity::getOrgId).collect(Collectors.toList()));
            Map<String, Object> params = shareQuery(query);
            List<SysOrgEntity> sysOrgEntityList = baseMapper.getList(params);
            Map<Long, SysOrgEntity> transferMap = sysOrgEntityList.stream().collect(Collectors.toMap(SysOrgEntity::getId, Function.identity()));
            page.getRecords().forEach(item -> {
                TransferOrgVO transferOrgVO = BeanUtil.copyProperties(transferMap.get(item.getOrgId()),TransferOrgVO.class);
                transferOrgVO.setTransferOrgId(item.getTransferOrgId());
                transferOrgVO.setNewOrgId(item.getNewOrgId());
                transferOrgVO.setTransId(item.getId());
                transferOrgVO.setAuditStatus(item.getAuditStatus());
                transferOrgVO.setId(item.getId());
                result.add(transferOrgVO);
            });
        }
        return new PageResult<>(result, page.getTotal());
    }

    @Override
    public void transfer(OrgTransferVO transferVO) {
        if (transferVO.getOrgId().equals(transferVO.getTransferOrgId())) {
            throw new ServerException("上级机构不能为自身");
        }
        if (transferVO.getTransferOrgId().equals(transferVO.getNewOrgId())) {
            throw new ServerException("请选择另外的工会");
        }
        SysOrgTransferEntity sysOrgTransferEntity = BeanUtil.copyProperties(transferVO, SysOrgTransferEntity.class);
        sysOrgTransferService.save(sysOrgTransferEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditTrans(Long transId) {
        SysOrgTransferEntity transferEntity = sysOrgTransferService.getById(transId);
        transferEntity.setAuditStatus(1);
        sysOrgTransferService.updateById(transferEntity);
        SysOrgEntity sysOrgEntity = this.getById(transferEntity.getOrgId());
        sysOrgEntity.setPid(transferEntity.getTransferOrgId());
        this.updateById(sysOrgEntity);
    }

    @Override
    public void manageAdmin(SysUserVO vo) {
        if (ObjectUtils.isNotEmpty(vo.getId())) {
            SysUserEntity entity = SysUserConvert.INSTANCE.convert(vo);

            // 判断用户名是否存在
            SysUserEntity user = sysUserDao.getByUsername(entity.getUsername());
            if (user != null && !user.getId().equals(entity.getId())) {
                throw new ServerException("用户名已经存在");
            }
            // 判断手机号是否存在
            user = sysUserDao.getByMobile(entity.getMobile());
            if (user != null && !user.getId().equals(entity.getId())) {
                throw new ServerException("手机号已经存在");
            }
            if (StringUtils.isNotEmpty(vo.getPassword())) {
                user.setPassword(passwordEncoder.encode(vo.getPassword()));
            }
            sysUserDao.updateById(user);
        } else {
            SysUserEntity entity = SysUserConvert.INSTANCE.convert(vo);
            entity.setSuperAdmin(SuperAdminEnum.NO.getValue());

            // 判断用户名是否存在
            SysUserEntity user = sysUserDao.getByUsername(entity.getUsername());
            if (user != null) {
                throw new ServerException("用户名已经存在");
            }

            // 判断手机号是否存在
            user = sysUserDao.getByMobile(entity.getMobile());
            if (user != null) {
                throw new ServerException("手机号已经存在");
            }
            if (StringUtils.isNotEmpty(vo.getPassword())) {
                entity.setPassword(passwordEncoder.encode(vo.getPassword()));
            }

            // 保存用户
            sysUserDao.insert(entity);
            SysOrgEntity sysOrgEntity = this.getById(vo.getOrgId());
            sysOrgEntity.setAdminId(entity.getId());
            this.updateById(sysOrgEntity);
        }
    }

    @Override
    public List<SysOrgMemberVO> getSysOrgMemberVO(Long id) {
        return BeanUtil.copyToList(sysOrgMemberDao.selectList(new LambdaQueryWrapper<SysOrgMemberEntity>().eq(SysOrgMemberEntity::getOrgId, id)), SysOrgMemberVO.class);
    }

    @Override
    public List<SysOrgVO> getList() {
        Map<String, Object> params = new HashMap<>();

        // 数据权限
        params.put(Constant.DATA_SCOPE, getDataScope("t1", "id"));

        // 机构列表
        List<SysOrgEntity> entityList = baseMapper.getList(params);
        entityList.sort(Comparator.comparingInt(SysOrgEntity::getSort).reversed());
        return TreeUtils.build(SysOrgConvert.INSTANCE.convertList(entityList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysOrgVO vo) {
        List<SysOrgEntity> list = this.list(new LambdaQueryWrapper<SysOrgEntity>().eq(SysOrgEntity::getName, vo.getName()));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new ServerException("组织名称有重复");
        }
        SysOrgEntity entity = BeanUtil.copyProperties(vo, SysOrgEntity.class);
        baseMapper.insert(entity);
        insertOegMember(vo, entity.getId());
    }

    /**
     * 设置委员信息
     *
     * @param vo 添加对象
     * @param id 主键
     */
    private void insertOegMember(SysOrgVO vo, Long id) {
        if (CollectionUtils.isNotEmpty(vo.getSysOrgMemberVOList())) {
            List<SysOrgMemberEntity> entityList = BeanUtil.copyToList(vo.getSysOrgMemberVOList(), SysOrgMemberEntity.class);
            entityList.forEach(item -> {
                item.setOrgId(id);
                item.setId(null);
                sysOrgMemberDao.insert(item);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysOrgVO vo) {
        SysOrgEntity entity = BeanUtil.copyProperties(vo, SysOrgEntity.class);

        // 上级机构不能为自身
        if (entity.getId().equals(entity.getPid())) {
            throw new ServerException("上级机构不能为自身");
        }

        // 上级机构不能为下级
        List<Long> subOrgList = getSubOrgIdList(entity.getId());
        if (subOrgList.contains(entity.getPid())) {
            throw new ServerException("上级机构不能为下级");
        }

        updateById(entity);

        sysOrgMemberDao.delete(new LambdaQueryWrapper<SysOrgMemberEntity>().eq(SysOrgMemberEntity::getOrgId, entity.getId()));
        insertOegMember(vo, entity.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        // 判断是否有子机构
        long orgCount = count(new QueryWrapper<SysOrgEntity>().eq("pid", id));
        if (orgCount > 0) {
            throw new ServerException("请先删除子机构");
        }

        // 判断机构下面是否有用户
        long userCount = sysUserDao.selectCount(new QueryWrapper<SysUserEntity>().eq("org_id", id));
        if (userCount > 0) {
            throw new ServerException("机构下面有用户，不能删除");
        }

        // 删除
        removeById(id);
    }

    @Override
    public void setVisible(List<? extends VisibleOrgBaseVO> list) {
        List<SysOrgEntity> orgEntities = this.list();
        if (CollectionUtils.isNotEmpty(orgEntities)) {
            Map<Long, SysOrgEntity> orgEntityMap = orgEntities.stream().collect(Collectors.toMap(SysOrgEntity::getId, Function.identity()));
            list.forEach(item -> {
                if (CollectionUtils.isNotEmpty(item.getVisibleOrg())) {
                    List<String> orgName = new ArrayList<>();
                    item.getVisibleOrg().forEach(orgItem -> {
                        if (ObjectUtils.isNotEmpty(orgEntityMap.get(orgItem))) {
                            orgName.add(orgEntityMap.get(orgItem).getName());
                        }
                    });
                    item.setVisibleOrgName(orgName);
                }
            });

        }
    }

    @Override
    public List<Long> getSubOrgIdList(Long id) {
        // 所有机构的id、pid列表
        List<SysOrgEntity> orgList = baseMapper.getIdAndPidList();

        // 递归查询所有子机构ID列表
        List<Long> subIdList = new ArrayList<>();
        getTree(id, orgList, subIdList);

        // 本机构也添加进去
        subIdList.add(id);

        return subIdList;
    }

    @Override
    public List<String> getNameList(List<Long> idList) {
        if (idList.isEmpty()) {
            return null;
        }

        return baseMapper.selectBatchIds(idList).stream().map(SysOrgEntity::getName).toList();
    }

    @Override
    public void setActivityJoinOrgName(ActivityJoinOrgBaseVO activityJoinOrgName) {
        if (CollectionUtils.isNotEmpty(activityJoinOrgName.getJoinOrgId())) {
            List<SysOrgEntity> sysOrgEntityList = this.listByIds(activityJoinOrgName.getJoinOrgId());
            activityJoinOrgName.setJoinOrgName(sysOrgEntityList.stream().map(SysOrgEntity::getName).collect(Collectors.toList()));
            ;
        }
    }

    private void getTree(Long id, List<SysOrgEntity> orgList, List<Long> subIdList) {
        for (SysOrgEntity org : orgList) {
            if (ObjectUtil.equals(org.getPid(), id)) {
                getTree(org.getId(), orgList, subIdList);

                subIdList.add(org.getId());
            }
        }
    }
}
